//
//  MFAPMConfig.m
//  MFAPMManager
//
//  Created by zhang liyu on 2019/5/22.
//

#import "MFAPMConfig.h"

#import "MFAPMNetMonitorURLProtocol.h"
#import "MFAPMAppLifeCircleProtocol.h"
#import "MFAPMScreenShotMonitor.h"
#import "MFAPMLocationMonitor.h"
#import "MFAPMRequestManager.h"
#import "MFAPMNetAOPProtocol.h"
#import "MFAPMDataFactory.h"
#import "MFAPMDefine.h"

@interface MFAPMConfig ()

/**
 是否开启监听功能 YES:开启 NO:关闭
 
 @default NO
 */
@property (nonatomic, readwrite, assign) BOOL apmEnable;

/**
 是否开启网络监听功能 YES:开启 NO:关闭
 
 @default NO
 */
@property (nonatomic, readwrite, assign) BOOL netErrorEnable;

/**
 是否开启崩溃监听功能 YES:开启 NO:关闭
 
 @default NO
 */
@property (nonatomic, readwrite, assign) BOOL crashEnable;

/**
 是否开启截屏监听功能 YES:开启 NO:关闭
 
 @default NO
 */
@property (nonatomic, readwrite, assign) BOOL screenshotEnable;

/**
 上传统计日志的时间间隔
 @default 5分钟
 */
@property (nonatomic, readwrite, assign) NSTimeInterval uploadInterval;

/**
 本地内存缓存日志的条数
 @default 100条
 */
@property (nonatomic, readwrite, assign) NSUInteger maxMemoryCacheNUM;

/**
 本地上传队列缓存日志的条数
 @default 500条
 */
@property (nonatomic, readwrite, assign) NSUInteger maxDiskCacheNUM;

/**
 单次上传最大事件条数
 
 @default 100条
 */
@property (nonatomic, readwrite, assign) NSUInteger maxReportCount;

/**
 截屏上传图片最大尺寸，单位KB
 
 @default 30KB
 */
@property (nonatomic, readwrite, assign) NSUInteger maxScreenShotUploadImgSize;

/**
 拦截网络请求startLoading和stopLoading回调数组
 
 @default 默认需要接收回调的中间件，如截图中间件
 */
@property (nonatomic, readwrite, strong) NSArray<MFAPMNetAOPProtocol> *interceptorsArr;

/**
 网络监听拦截请求的白名单
 
 @default 从服务端获取到的默认列表，若为空则拦截全部请求
 */
@property (nonatomic, readwrite, strong) NSArray<NSString *> *netMonitorWhiteHostArr;

/**
 截屏上报白名单数组，在数组内的对象会被上报截屏相关信息
 */
@property (nonatomic, readwrite, strong) NSArray<NSString *> *screenShotWhiteHostArr;

/**
 应用生命周期监听白名单数组，在数组内的对象会被上报应用生命周期函数调用的相关信息
 */
@property (nonatomic, readwrite, strong) NSArray<MFAPMAppLifeCircleProtocol> *appLifeCircleWhiteHostArr;
/**
 更新网络监听中间件队列
 */
@property (nonatomic, readwrite, strong) dispatch_queue_t netInterceptorQueue;

/**
 更新截屏事件获取中间件队列
 */
@property (nonatomic, readwrite, strong) dispatch_queue_t screenShotInterceptorQueue;

/**
 app生命周期事件获取中间件队列
 */
@property (nonatomic, strong) dispatch_queue_t appLifeCircleInterceptorQueue;

@end

@implementation MFAPMConfig

#pragma mark - Singleton

+ (instancetype)defaultConfigure{
    static MFAPMConfig *defaultConfig = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        defaultConfig = [[MFAPMConfig alloc] init];
    });
    return defaultConfig;
}

#pragma mark - Fetch Config

- (void)fetchSettingConfigWithComplete:(void (^)(void))complete{
    //发送请求，获取当前Manager的配置信息
    [MFAPMRequestManager POST:MFAPM_REQUEST_URL_CONFIG parametersDict:@{@"appKey" : MFAPM_APP_KEY} success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        NSDictionary *responseDict = (NSDictionary *)responseObject;
        if(![responseDict isKindOfClass:[NSDictionary class]]
           || [responseDict[@"code"] integerValue] != 0
           || ![responseDict[@"data"] isKindOfClass:[NSDictionary class]]
           || [(NSDictionary *)responseDict[@"data"] count] == 0){
            //数据不符规范，进行错误处理，关闭监听
            [self handleConfigRequestFailure];
            
            if(complete){
                complete();
            }
            return;
        }
        //请求结果获取后，进行配置项设定
        [self configMonitorWithSettingsDict:(NSDictionary *)responseDict[@"data"]];
        
        if(complete){
            complete();
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        //请求错误，关闭监听
        [self handleConfigRequestFailure];
        
        if(complete){
            complete();
        }
    }];
}

- (void)configMonitorWithSettingsDict:(NSDictionary *)settingDict{
    
    //总开关关闭时，关闭监听，重置选项后返回
    _apmEnable = ([settingDict[@"apmSwitch"] integerValue] == 1);
    if(!_apmEnable){
        [self handleConfigRequestFailure];
        return;
    }
    
    //判断服务是否开启
    
    //网络请求监听
    _netErrorEnable = ([settingDict[@"errorSwitch"] integerValue] == 1);
    //崩溃监听
    _crashEnable = ([settingDict[@"crashSwitch"] integerValue] == 1);
    //截图监听
    _screenshotEnable = ([settingDict[@"screenshotSwitch"] integerValue] == 1);
    
    
    //属性配置
    _uploadInterval = [settingDict[@"timeStep"] integerValue];
    if(_uploadInterval <= 0){
        _uploadInterval = kMFAPMConfigDefaultUploadInterval;
    }
    
    _maxMemoryCacheNUM = [settingDict[@"memoryCacheCount"] integerValue];
    if(_maxMemoryCacheNUM < 0){
        _maxMemoryCacheNUM = kMFAPMConfigDefaultMemoryMaxCacheItemNUM;
    }
    
    _maxDiskCacheNUM = [settingDict[@"diskCacheCount"] integerValue];
    if(_maxDiskCacheNUM <= 0){
        _maxDiskCacheNUM = kMFAPMConfigDefaultDiskMaxCacheItemNUM;
    }
    
    _maxReportCount = [settingDict[@"maxReportCount"] integerValue];
    if(_maxReportCount <= 0){
        _maxReportCount = kMFAPMConfigDefaultSingleRequestMaxUploadItemNUM;
    }
    
    _maxScreenShotUploadImgSize = [settingDict[@"fileSize"] integerValue];
    if(_maxScreenShotUploadImgSize <= 0){
        _maxScreenShotUploadImgSize = kMFAPMConfigDefaultScreenShotUploadImgSize;
    }
    
    //更新白名单列表
    NSArray *responseWhiteListArr = settingDict[@"whiteList"];
    if(![responseWhiteListArr isKindOfClass:[NSArray class]] || responseWhiteListArr.count == 0){
        _netMonitorWhiteHostArr = [NSArray array];
    }else{
        _netMonitorWhiteHostArr = [NSArray arrayWithArray:responseWhiteListArr];
    }
    
    //更新监听网络的中间件为默认值
    _interceptorsArr = (NSArray<MFAPMNetAOPProtocol> *)[NSArray arrayWithObjects:[MFAPMScreenShotMonitor sharedInstance], nil];
    _appLifeCircleWhiteHostArr = (NSArray<MFAPMAppLifeCircleProtocol> *)[NSArray arrayWithObjects:[MFAPMDataFactory sharedInstance], [MFAPMLocationMonitor sharedInstance], nil];
}

- (void)handleConfigRequestFailure{
    //关闭所有监听功能，重置属性为默认值
    _apmEnable = NO;
    _netErrorEnable = NO;
    _crashEnable = NO;
    _screenshotEnable = NO;
    
    //非可配置项设定为默认值
    _uploadInterval = kMFAPMConfigDefaultUploadInterval;
    _maxMemoryCacheNUM = kMFAPMConfigDefaultMemoryMaxCacheItemNUM;
    _maxDiskCacheNUM = kMFAPMConfigDefaultDiskMaxCacheItemNUM;
    _maxReportCount = kMFAPMConfigDefaultSingleRequestMaxUploadItemNUM;
    _maxScreenShotUploadImgSize = kMFAPMConfigDefaultScreenShotUploadImgSize;
    
    //更新白名单列表为默认值
    _netMonitorWhiteHostArr = [NSArray array];
    //更新监听网络的中间件为默认值
    _interceptorsArr = (NSArray<MFAPMNetAOPProtocol> *)[NSArray arrayWithObjects:[MFAPMScreenShotMonitor sharedInstance], nil];
    _appLifeCircleWhiteHostArr = (NSArray<MFAPMAppLifeCircleProtocol> *)[NSArray arrayWithObjects:[MFAPMDataFactory sharedInstance], [MFAPMLocationMonitor sharedInstance], nil];
}

#pragma mark - Net Monitor Actions

- (NSArray<MFAPMNetAOPProtocol> *)fetchNetMonitorURLProtocolInterceptors{
    __block NSArray<MFAPMNetAOPProtocol> *resultArr = nil;
    __weak typeof(&*self) weakSelf = self;
    dispatch_sync(self.netInterceptorQueue, ^{
        __strong typeof(&*self) strongSelf = weakSelf;
        resultArr = (NSArray<MFAPMNetAOPProtocol> *)[NSArray arrayWithArray:strongSelf.interceptorsArr];
    });
    return resultArr;
}

- (void)updateNetMonitorURLProtocolInterceptors:(NSArray<MFAPMNetAOPProtocol> *)interceptorsArr{
    __weak typeof(&*self) weakSelf = self;
    dispatch_sync(self.netInterceptorQueue, ^{
        __strong typeof(&*self) strongSelf = weakSelf;
        //需要测试
        strongSelf.interceptorsArr = (NSArray<MFAPMNetAOPProtocol> *)[NSArray arrayWithArray:interceptorsArr];
    });
}

#pragma mark - ScreenShot Monitor

- (NSArray *)fetchScreenShotInterceptors{
    __block NSArray *resultArr = nil;
    __weak typeof(&*self) weakSelf = self;
    dispatch_sync(self.screenShotInterceptorQueue, ^{
        __strong typeof(&*self) strongSelf = weakSelf;
        resultArr = [NSArray arrayWithArray:strongSelf.screenShotWhiteHostArr];
    });
    return resultArr;
}

- (void)updateScreenShotInterceptors:(NSArray *)interceptorsArr{
    __weak typeof(&*self) weakSelf = self;
    dispatch_sync(self.screenShotInterceptorQueue, ^{
        __strong typeof(&*self) strongSelf = weakSelf;
        strongSelf.screenShotWhiteHostArr = [NSArray arrayWithArray:interceptorsArr];
    });
}

#pragma mark - App Life Circle Actions

- (NSArray<MFAPMAppLifeCircleProtocol> *)fetchAppLifeCircleInterceptors{
    __block NSArray *resultArr = nil;
    __weak typeof(&*self) weakSelf = self;
    dispatch_sync(self.appLifeCircleInterceptorQueue, ^{
        __strong typeof(&*self) strongSelf = weakSelf;
        resultArr = [NSArray arrayWithArray:strongSelf.appLifeCircleWhiteHostArr];
    });
    return (NSArray<MFAPMAppLifeCircleProtocol> *)resultArr;
}

- (void)updateAppLifeCircleInterceptors:(NSArray<MFAPMAppLifeCircleProtocol> *)interceptorsArr{
    __weak typeof(&*self) weakSelf = self;
    dispatch_sync(self.appLifeCircleInterceptorQueue, ^{
        __strong typeof(&*self) strongSelf = weakSelf;
        strongSelf.appLifeCircleWhiteHostArr = (NSArray<MFAPMAppLifeCircleProtocol> *)[NSArray arrayWithArray:interceptorsArr];
    });
}

#pragma mark - Setter & Getter

- (dispatch_queue_t)netInterceptorQueue{
    if(!_netInterceptorQueue){
        _netInterceptorQueue = dispatch_queue_create("cn.missFresh.APM.NetUpdateInterceptorQueue", DISPATCH_QUEUE_SERIAL);
    }
    return _netInterceptorQueue;
}

- (dispatch_queue_t)screenShotInterceptorQueue{
    if(!_screenShotInterceptorQueue){
        _screenShotInterceptorQueue = dispatch_queue_create("cn.missFresh.APM.ScreenShotInterceptorQueue", DISPATCH_QUEUE_SERIAL);
    }
    return _screenShotInterceptorQueue;
}

- (dispatch_queue_t)appLifeCircleInterceptorQueue{
    if(!_appLifeCircleInterceptorQueue){
        _appLifeCircleInterceptorQueue = dispatch_queue_create("cn.missFresh.APM.AppLifeCircleInterceptorQueue", DISPATCH_QUEUE_SERIAL);
    }
    return _appLifeCircleInterceptorQueue;
}

@end
